/* QtLua -- Lua bindings for Qt
   Copyright (C) 2011, Jarek Pelczar

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA

*/

#include "qluascriptsdebuggerscriptmodel_p.h"
#include "qluascriptprogram.h"
#include "qluascriptengine_p.h"
#include <QCoreApplication>
#include <QList>
#include <QDebug>

class QLuaScriptsDebuggerScriptModelPrivate
{
public:
    struct Node
    {
        qint64 scriptId;
        QLuaScriptProgram program;
    };

    QLuaScriptsDebuggerScriptModelPrivate();
    ~QLuaScriptsDebuggerScriptModelPrivate();

    QList<Node *> nodes;
};

QLuaScriptsDebuggerScriptModelPrivate::QLuaScriptsDebuggerScriptModelPrivate()
{
}

QLuaScriptsDebuggerScriptModelPrivate::~QLuaScriptsDebuggerScriptModelPrivate()
{
    qDeleteAll(nodes);
}

QLuaScriptsDebuggerScriptModel::QLuaScriptsDebuggerScriptModel(QObject *parent) :
    QAbstractItemModel(parent)
{
    d = new QLuaScriptsDebuggerScriptModelPrivate();
}

QLuaScriptsDebuggerScriptModel::~QLuaScriptsDebuggerScriptModel()
{
    delete d;
}

QModelIndex QLuaScriptsDebuggerScriptModel::index(int row, int column, const QModelIndex &parent) const
{
    if(parent.isValid())
        return QModelIndex();
    if(row < 0 || row >= d->nodes.count())
        return QModelIndex();
    if(column  < 0 || column >= columnCount())
        return QModelIndex();
    return createIndex(row, column);
}

QModelIndex QLuaScriptsDebuggerScriptModel::parent(const QModelIndex &child) const
{
    return QModelIndex();
}

int QLuaScriptsDebuggerScriptModel::rowCount(const QModelIndex &parent) const
{
    if(!parent.isValid())
        return d->nodes.count();
    return 0;
}

int QLuaScriptsDebuggerScriptModel::columnCount(const QModelIndex &parent) const
{
    if(!parent.isValid())
        return 3;
    return 0;
}

QVariant QLuaScriptsDebuggerScriptModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid() || index.row() >= d->nodes.count())
        return QVariant();
    const QLuaScriptsDebuggerScriptModelPrivate::Node * node = d->nodes[index.row()];
    if(role == Qt::DisplayRole) {
        if(index.column() == 0)
            return node->scriptId;
        if(index.column() == 1)
            return node->program.fileName();
        if(index.column() == 2) {
            QLuaScriptProgram::ScriptType type = node->program.type();
            if(type == QLuaScriptProgram::ByteCode)
                return tr("Compiled");
            return tr("Text");
        }
    }
    return QVariant();
}

QVariant QLuaScriptsDebuggerScriptModel::headerData(int section, Qt::Orientation orientation,
                            int role) const
{
    if(orientation == Qt::Horizontal && role == Qt::DisplayRole) {
        switch(section)
        {
        case 0: return tr("ID");
        case 1: return tr("Location");
        case 2: return tr("Type");
        default: break;
        }
    }
    return QVariant();
}

void QLuaScriptsDebuggerScriptModel::addScript(qint64 id, const QLuaScriptProgram& program)
{
#ifdef QT_DEBUG
    qDebug() << "[QtLua] Add script" << id << program.isNull();
#endif
    beginInsertRows(QModelIndex(), d->nodes.count(), d->nodes.count());
    QLuaScriptsDebuggerScriptModelPrivate::Node * node = new QLuaScriptsDebuggerScriptModelPrivate::Node;
    d->nodes.append(node);
    node->program = program;
    node->scriptId = id;
    endInsertRows();
}

void QLuaScriptsDebuggerScriptModel::removeScript(qint64 id)
{
    for(int i = 0 ; i < d->nodes.count() ; ++i) {
        if(d->nodes[i]->scriptId == id) {
            beginRemoveRows(QModelIndex(), i, i);
            delete d->nodes[i];
            d->nodes.removeAt(i);
            endRemoveRows();
            return;
        }
    }
}

void QLuaScriptsDebuggerScriptModel::attachEngine(QLuaScriptEngine * engine)
{
    QHashIterator<qint64, QLuaScriptProgram> it(engine->loadedScripts());
    beginResetModel();
    qDeleteAll(d->nodes);
    d->nodes.clear();
    while(it.hasNext()) {
        it.next();
        QLuaScriptsDebuggerScriptModelPrivate::Node * node = new QLuaScriptsDebuggerScriptModelPrivate::Node;
        d->nodes.append(node);
        node->scriptId = it.key();
        node->program = it.value();
    }
    endResetModel();
}

void QLuaScriptsDebuggerScriptModel::detachEngine()
{
    beginResetModel();
    qDeleteAll(d->nodes);
    d->nodes.clear();
    endResetModel();
}

QLuaScriptProgram QLuaScriptsDebuggerScriptModel::program(qint64 id)
{
    for(int i = 0 ; i < d->nodes.count() ; ++i)
        if(d->nodes[i]->scriptId == id)
            return d->nodes[i]->program;
    return QLuaScriptProgram();
}
